/*
 * cpuload.c
 */

#include "cpuload.h"

#include <stdint.h>
#include "systick.h"
#include "xds.h"

typedef struct
{
	/// data
	uint16_t	beginTime_us;
	uint16_t	cntRunTime;
	uint32_t	sumRunTime_us;

	/// load
	uint8_t		cpuload_pct;	/// 0~255%
	uint16_t	aveRunTime_us;

	/// time
	uint16_t	time_ms;
	uint16_t	time_sec;
}
Cpuload_Data_T;

Cpuload_Data_T	Cpuload_Data;

uint8_t Cpuload_GetCpuloadPct(void)
{
	return Cpuload_Data.cpuload_pct;
}

void Cpuload_Init(void)
{
	Cpuload_Data.time_ms = 0;
	Cpuload_Data.time_sec = 0;
}

void Cpuload_Task400ms(void)
{
	uint32_t calc;

	/// time
	Cpuload_Data.time_ms += 400;
	if(Cpuload_Data.time_ms>=1000)
	{
		Cpuload_Data.time_ms -= 1000;
		Cpuload_Data.time_sec++;
	}

	/// calculate cpuload
	calc = Cpuload_Data.sumRunTime_us;
	calc /= 1000;	/// us -> ms
	calc *= 100;	/// * 100%
	calc /= 400;	/// / 400ms
	if(calc>0xFF) calc = 0xFF;
	Cpuload_Data.cpuload_pct = (uint8_t)calc;

	/// average time
	if(Cpuload_Data.cntRunTime>0)
	{
		calc = Cpuload_Data.sumRunTime_us;
		calc /= Cpuload_Data.cntRunTime;
		if(calc>0xFFFF) calc = 0xFFFF;
		Cpuload_Data.aveRunTime_us = (uint16_t)calc;
	}

	/// output
	xds_printf(XDS_USER_OS, XDS_LEVEL_INFO, "-_-\n");

	/// next cycle
	Cpuload_Data.sumRunTime_us = 0;
	Cpuload_Data.cntRunTime = 0;
}

void Cpuload_BeforeEnterTask(void)
{
	/// record start time
	Cpuload_Data.beginTime_us = SysTick_GetTimeUs();
}

void Cpuload_AfterExitTask(void)
{
	/// record end time
	uint16_t time = SysTick_GetTimeUs();
	/// diff time
	uint16_t diff = time - Cpuload_Data.beginTime_us;
	/// count and sum runtime
	Cpuload_Data.cntRunTime++;
	Cpuload_Data.sumRunTime_us += diff;
}

